package com.janetfilter.core;

import com.janetfilter.core.utils.ProcessUtils;
import com.janetfilter.core.utils.StringUtils;

import java.io.File;
import java.lang.instrument.Instrumentation;

/**
 * 环境配置类，负责管理框架运行所需的所有配置信息和路径
 * 包括配置文件目录、插件目录、日志目录等
 * 同时存储Instrumentation实例以供框架使用
 */
public final class Environment {
    // 当前进程ID
    private final String pid;
    // 框架版本
    private final String version;
    // 版本号（数字形式）
    private final int versionNumber;
    // 应用名称，用于多应用隔离配置
    private final String appName;
    // 基础目录（通常是jar文件所在目录）
    private final File baseDir;
    // Agent文件路径
    private final File agentFile;
    // 配置文件目录
    private final File configDir;
    // 插件目录
    private final File pluginsDir;
    // 日志目录
    private final File logsDir;
    // 本地方法前缀，用于设置native方法前缀
    private final String nativePrefix;
    // 禁用插件的后缀名
    private final String disabledPluginSuffix;
    // 是否为Attach模式
    private final boolean attachMode;

    // Java Instrumentation实例，提供类重定义和转换的能力
    private final Instrumentation instrumentation;

    /**
     * 创建环境实例（不指定应用名）
     *
     * @param instrumentation Instrumentation实例
     * @param agentFile Agent文件
     * @param attachMode 是否为Attach模式
     */
    public Environment(Instrumentation instrumentation, File agentFile, boolean attachMode) {
        this(instrumentation, agentFile, null, attachMode);
    }

    /**
     * 创建环境实例（指定应用名）
     *
     * @param instrumentation Instrumentation实例
     * @param agentFile Agent文件
     * @param app 应用名，用于隔离不同应用的配置
     * @param attachMode 是否为Attach模式
     */
    public Environment(Instrumentation instrumentation, File agentFile, String app, boolean attachMode) {
        this.instrumentation = instrumentation;
        this.agentFile = agentFile;
        baseDir = agentFile.getParentFile();

        // 如果未指定应用名，使用默认目录
        // 否则，使用应用名作为目录后缀，实现多应用配置隔离
        if (StringUtils.isEmpty(app)) {
            appName = "";
            configDir = new File(baseDir, "config");
            pluginsDir = new File(baseDir, "plugins");
            logsDir = new File(baseDir, "logs");
        } else {
            appName = app.toLowerCase();
            configDir = new File(baseDir, "config-" + appName);
            pluginsDir = new File(baseDir, "plugins-" + appName);
            logsDir = new File(baseDir, "logs-" + appName);
        }

        // 获取当前进程ID
        pid = ProcessUtils.currentId();
        // 设置版本信息
        version = Launcher.VERSION;
        versionNumber = Launcher.VERSION_NUMBER;
        // 生成随机方法前缀，用于native方法前缀
        nativePrefix = StringUtils.randomMethodName(15) + "_";
        // 设置禁用插件的后缀
        disabledPluginSuffix = ".disabled.jar";
        this.attachMode = attachMode;
    }

    /**
     * 获取当前进程ID
     * @return 进程ID
     */
    public String getPid() {
        return pid;
    }

    /**
     * 获取框架版本
     * @return 版本字符串
     */
    public String getVersion() {
        return version;
    }

    /**
     * 获取框架版本号
     * @return 版本号
     */
    public int getVersionNumber() {
        return versionNumber;
    }

    /**
     * 获取应用名称
     * @return 应用名
     */
    public String getAppName() {
        return appName;
    }

    /**
     * 获取基础目录
     * @return 基础目录文件对象
     */
    public File getBaseDir() {
        return baseDir;
    }

    /**
     * 获取Agent文件
     * @return Agent文件对象
     */
    public File getAgentFile() {
        return agentFile;
    }

    /**
     * 获取配置目录
     * @return 配置目录文件对象
     */
    public File getConfigDir() {
        return configDir;
    }

    /**
     * 获取插件目录
     * @return 插件目录文件对象
     */
    public File getPluginsDir() {
        return pluginsDir;
    }

    /**
     * 获取日志目录
     * @return 日志目录文件对象
     */
    public File getLogsDir() {
        return logsDir;
    }

    /**
     * 获取native方法前缀
     * @return native方法前缀
     */
    public String getNativePrefix() {
        return nativePrefix;
    }

    /**
     * 获取禁用插件的后缀
     * @return 禁用插件后缀
     */
    public String getDisabledPluginSuffix() {
        return disabledPluginSuffix;
    }

    /**
     * 是否为Attach模式
     * @return 如果是Attach模式则返回true
     */
    public boolean isAttachMode() {
        return attachMode;
    }

    /**
     * 是否为Java Agent模式
     * @return 如果是Java Agent模式则返回true
     */
    public boolean isJavaagentMode() {
        return !attachMode;
    }

    /**
     * 获取Instrumentation实例
     * @return Instrumentation实例
     */
    public Instrumentation getInstrumentation() {
        return instrumentation;
    }

    /**
     * 返回环境信息的字符串表示
     * @return 环境信息字符串
     */
    @Override
    public String toString() {
        return "Environment: {" +
                "\n\tpid = " + pid +
                ", \n\tversion = " + version +
                ", \n\tversionNumber = " + versionNumber +
                ", \n\tappName = " + appName +
                ", \n\tbaseDir = " + baseDir +
                ", \n\tagentFile = " + agentFile +
                ", \n\tconfigDir = " + configDir +
                ", \n\tpluginsDir = " + pluginsDir +
                ", \n\tlogsDir = " + logsDir +
                ", \n\tnativePrefix = " + nativePrefix +
                ", \n\tdisabledPluginSuffix = " + disabledPluginSuffix +
                ", \n\tattachMode = " + attachMode +
                "\n}";
    }
}
